#include <stdio.h>
#include "devices/timer.h"
#include "threads/thread.h"
#include "threads/interrupt.h"
#include "threads/init.h"
#include "tests/threads/tests.h"
#include "tests/threads/test_o1.h"
#include "lib/stdlib.h"


#define SLEEP_TIME 10
#define TASK_TIME 15
static uint64_t start_cycles = 0;
static inline uint64_t get_cycles (void)
{
	  uint64_t ret = 0;
	    __asm__ __volatile__("rdtsc" : "=A" (ret));
		  return ret;
}

int64_t wakeup_ticks;
static void mytest_func(void* t_ UNUSED)
{
	int s=0;

	while(timer_ticks() <= wakeup_ticks)
	{
		s += 10;
		s %= 0xff;
	}
	//Doing useless job for waiting
}
static void
test_thread(int thread_cnt){
	int i;
	/*
	int64_t sched_ticks;
	int64_t sched_start_ticks;
	*/
	int64_t sched_start_cycle;
	int64_t sched_cycle;
	enum intr_level old_level;
	struct thread *t;

	wakeup_ticks = timer_ticks() + 30 + thread_cnt*100;
	msg("Creating %d threads to doing given tasks", thread_cnt);
	old_level = intr_disable();
	for(i = 0; i < thread_cnt; i++)
	{
		char name[16];
		snprintf(name, sizeof name, "thread %i", i);
		thread_create(name, (i%(PRI_MAX+1-PRI_MIN))+PRI_MIN, mytest_func, NULL);
	}
	//Does not interrupted for scheduling while creating test thread
	
	sched_start_cycle = get_cycles();
	for(i = 0; i < 30; i++)
	{
		t = test_next_thread_to_run();
	}
	sched_cycle = get_cycles() - sched_start_cycle;
	intr_set_level(old_level);
	wakeup_ticks = timer_ticks();
	//Make all thread to wakeup
	timer_sleep(10);
	//Wait while whole thread to wake
	msg("Thread : %d, Schedule cycles : %d", thread_cnt, sched_cycle);
	thread_print_stats();
}
void test_o1 (void) 
{
	int i;
	for(i = 10; i <= 1300; i+=10)
		test_thread(i);
}
